#pragma once

template <typename Key, typename Val, bool isConst>
_hIntervalMapIterator<Key, Val, isConst>::_hIntervalMapIterator(MapTy* pMap, NodeTy* pNode, ValNodeTy* pValNode)
{
	_pMap = pMap;
	_pNode = pNode;
	_pValNode = pValNode;
}

template <typename Key, typename Val, bool isConst>
auto _hIntervalMapIterator<Key, Val, isConst>::operator->()
{
	assert(_pMap);
	assert(_pNode);
	assert(_pNode != NodeTy::_pNil);
	assert(_pValNode);
	return std::make_shared<RetPr>(std::piecewise_construct, std::tuple<KeyRef>(_pNode->_key), std::tuple<ValRef>(*_pValNode->_data));
}

template <typename Key, typename Val, bool isConst>
auto _hIntervalMapIterator<Key, Val, isConst>::operator*()
{
	assert(_pMap);
	assert(_pNode);
	assert(_pNode != NodeTy::_pNil);
	assert(_pValNode);
	return std::make_pair(KeyRef(_pNode->_key), ValRef(*_pValNode->_data));
}

template <typename Key, typename Val, bool isConst>
auto& _hIntervalMapIterator<Key, Val, isConst>::operator++()
{
	assert(_pMap);
	assert(_pNode);
	assert(_pNode != NodeTy::_pNil);
	assert(_pValNode);
	assert(_pValNode != &_pNode->_valList._node);

	_pValNode = _pValNode->next(false);
	if (_pValNode != &_pNode->_valList._node)
		return *this;

	_pNode = _pNode->getNextNode();
	_pValNode = _pNode->_valList._node.next(false);
	return *this;
}

template <typename Key, typename Val, bool isConst>
auto _hIntervalMapIterator<Key, Val, isConst>::operator++(int)
{
	assert(_pMap);
	assert(_pNode);
	assert(_pNode != NodeTy::_pNil);
	assert(_pValNode);
	assert(_pValNode != &_pNode->_valList._node);

	ThisTy it = *this;	
	_pValNode = _pValNode->next(false);
	if (_pValNode != &_pNode->_valList._node)
		return it;

	_pNode = _pNode->getNextNode();
	_pValNode = _pNode->_valList._node.next(false);
	return it;
}

template <typename Key, typename Val, bool isConst>
bool _hIntervalMapIterator<Key, Val, isConst>::operator==(const _hIntervalMapIterator& other) const
{ 
	if (_pMap != other._pMap)
		return false;

	if (_pNode != other._pNode)
		return false;

	if (_pNode != NodeTy::_pNil)
		return _pValNode == other._pValNode;

	return true;
}
